package com.easychat.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.easychat.entity.config.AppConfig;
import com.easychat.entity.constants.Constants;
import com.easychat.entity.dto.MessageSendDto;
import com.easychat.entity.dto.TokenUserInfoDto;
import com.easychat.entity.enums.*;
import com.easychat.entity.po.*;
import com.easychat.entity.query.*;
import com.easychat.entity.vo.UserInfoVo;
import com.easychat.exception.BusinessException;
import com.easychat.mappers.*;
import com.easychat.redis.RedisCache;
import com.easychat.redis.RedisComponent;
import com.easychat.service.ChatSessionUserService;
import com.easychat.service.UserContactService;
import com.easychat.websocket.netty.MessageHandler;
import jodd.util.ArraysUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.easychat.entity.vo.PaginationResultVO;
import com.easychat.service.UserInfoService;
import com.easychat.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


/**
 * 用户信息表 业务接口实现
 */
@Service("userInfoService")
public class UserInfoServiceImpl implements UserInfoService {

	@Resource
	private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
	@Resource
	private UserInfoBeautyMapper<UserInfoBeauty, UserInfoBeautyQuery> userInfoBeautyMapper;

	@Resource
	private RedisComponent redisComponent;
	@Resource
	private UserContactService userContactService;

	@Resource
	private UserContactMapper userContactMapper;
	@Resource
	private RedisCache redisCache;
	@Resource
	private ChatMessageMapper<ChatMessage,ChatMessageQuery> chatMessageMapper;
	@Resource
	private ChatSessionUserService chatSessionUserService;
	@Resource
	private MessageHandler messageHandler;
	@Resource
	private ChatSessionUserMapper<ChatSessionUser,ChatSessionUserQuery> chatSessionUserMapper;
	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<UserInfo> findListByParam(UserInfoQuery param) {
		return this.userInfoMapper.selectList(param);
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(UserInfoQuery param) {
		return this.userInfoMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<UserInfo> findListByPage(UserInfoQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<UserInfo> list = this.findListByParam(param);
		PaginationResultVO<UserInfo> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(UserInfo bean) {
		return this.userInfoMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<UserInfo> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userInfoMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<UserInfo> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.userInfoMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(UserInfo bean, UserInfoQuery param) {
		StringTools.checkParam(param);
		return this.userInfoMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(UserInfoQuery param) {
		StringTools.checkParam(param);
		return this.userInfoMapper.deleteByParam(param);
	}

	/**
	 * 根据UserId获取对象
	 */
	@Override
	public UserInfo getUserInfoByUserId(String userId) {
		return this.userInfoMapper.selectByUserId(userId);
	}

	/**
	 * 根据UserId修改
	 */
	@Override
	public Integer updateUserInfoByUserId(UserInfo bean, String userId) {
		return this.userInfoMapper.updateByUserId(bean, userId);
	}

	/**
	 * 根据UserId删除
	 */
	@Override
	public Integer deleteUserInfoByUserId(String userId) {
		return this.userInfoMapper.deleteByUserId(userId);
	}

	/**
	 * 根据Email获取对象
	 */
	@Override
	public UserInfo getUserInfoByEmail(String email) {
		return this.userInfoMapper.selectByEmail(email);
	}

	/**
	 * 根据Email修改
	 */
	@Override
	public Integer updateUserInfoByEmail(UserInfo bean, String email) {
		return this.userInfoMapper.updateByEmail(bean, email);
	}

	/**
	 * 根据Email删除
	 */
	@Override
	public Integer deleteUserInfoByEmail(String email) {
		return this.userInfoMapper.deleteByEmail(email);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)//开启事务，因为操作了2张表，如果失败回滚
	public void register(String email, String password, String nickName) {
		//1.验证email是否已经被注册
		UserInfo userInfo = userInfoMapper.selectByEmail(email);
		if (userInfo!=null){
			throw new BusinessException("该邮箱已被注册");
		}
		//2.生成userId  （qq号 微信号）
		String userId = StringTools.getUserId();
			//2.1 判断是否能生成靓号
		UserInfoBeauty userInfoBeauty = userInfoBeautyMapper.selectByEmail(email);//是否是靓号用户？
		Boolean isBeautyUser=  userInfoBeauty!=null //是靓号用户 && 该用户的靓号未使用
				&& userInfoBeauty.getStatus().equals(BeautyAccountStatusEnum.NO_USE.getStatus());
		if (isBeautyUser){
			userId= UserContactTypeEnum.USER.getPrefix()+ userInfoBeauty.getUserId();
		}
		//3.密码加密
		String encodePassword = StringTools.encodeMD5(password);
		//创建时间
		Date curDate = new Date();
		//完成注册，添加到数据库
		UserInfo newUser = new UserInfo();
		newUser.setUserId(userId);
		newUser.setEmail(email);
		newUser.setPassword(encodePassword);
		newUser.setNickName(nickName);
		newUser.setCreateTime(curDate);
		newUser.setStatus(UserStatusEnum.ENABLE.getStatus());
		newUser.setLastOffTime(curDate.getTime());
		newUser.setJoinType(JoinTypeEnum.APPLY.getType());
		userInfoMapper.insert(newUser);

		//设置靓号状态
		if (isBeautyUser){
			UserInfoBeauty updateBeauty = new UserInfoBeauty();
			updateBeauty.setStatus(BeautyAccountStatusEnum.USEED.getStatus());
			userInfoBeautyMapper.updateById(updateBeauty,userInfoBeauty.getId());
		}

		//创建机器人好友
		userContactService.addContactRobot(userId);


	}
	@Resource
	private AppConfig appConfig;
	@Override
	public TokenUserInfoDto login(String email, String password) {
		UserInfo userInfo = userInfoMapper.selectByEmail(email);
		if (userInfo==null || !password.equals(userInfo.getPassword())){
			throw  new BusinessException("账号不存在或密码不正确");
		}
		if (userInfo.getStatus().equals(UserStatusEnum.DISABLE)){
			throw  new BusinessException("账号被禁用");
		}

		//判断是否已经登录 通过心跳
		Long LastUserHeartBeat = redisComponent.getUserHeartBeat(userInfo.getUserId());
		if (LastUserHeartBeat!=null){
			throw new BusinessException("该账号已在别处登录，请勿重复登录");
		}

		//查询联系人
		UserContactQuery userContactQuery = new UserContactQuery();
		userContactQuery.setUserId(userInfo.getUserId());
		userContactQuery.setStatus(UserContactStatusEnum.FRIEND.getCode());
		List<UserContact> list = userContactMapper.selectList(userContactQuery);
		List<String> contactIdList = list.stream().map(item -> item.getContactId()).collect(Collectors.toList());
		redisComponent.deleteUserContact(userInfo.getUserId());
		if (!contactIdList.isEmpty()){
			redisComponent.addUserContactBatch(userInfo.getUserId(),contactIdList);
		}


		// 生成tokenDto对象
		TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto(userInfo);
		// 生成token
		String token = userInfo.getUserId()+ StringTools.getRandomString(Constants.LENGTH_20);
		tokenUserInfoDto.setToken(token);
		//把token存入redis
		redisComponent.setTokenUserInfoDto(tokenUserInfoDto);

		return tokenUserInfoDto;

	}

    @Override
    public UserInfoVo getContactInfo(String contactId) {
		UserInfo userInfo = userInfoMapper.selectByUserId(contactId);
		if (userInfo==null){
			throw new BusinessException("找不到该用户");
		}
		UserInfoVo userInfoVo = new UserInfoVo();
		//将userInfo的属性值拷贝到userInfoVo
		BeanUtils.copyProperties(userInfo, userInfoVo);
		return userInfoVo;
    }

	/**
	 * 更改用户信息
	 * @param userInfo
	 * @param avatarFile
	 * @param avatarCover
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
    public void updateUserInfo(UserInfo userInfo, MultipartFile avatarFile, MultipartFile avatarCover) throws IOException {
		//如果头像不为空，说明要换头像了，那么图片需要上传，通过userId的命名方式，覆盖了旧的头像文件
		if (avatarFile!=null){
			//基本路径  /file/
			String baseFolder = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE;
			//图片路径 /file/avatar/
			File targetFileFolder = new File(baseFolder+Constants.FILE_FOLDER_AVATAR_NAME);
			if (!targetFileFolder.exists()){
				targetFileFolder.mkdirs();
			}
			//     /file/avatar/{userId}.png  文件名
			String fileName = targetFileFolder+"/"+userInfo.getUserId()+ Constants.IMAGE_SUFFIX;
			avatarFile.transferTo(new File(fileName));
			//     /file/avatar/{userId}.png_cover.png  文件名
			String coverFileName = fileName+ Constants.COVER_IMAGE_SUFFIX;
			avatarCover.transferTo(new File(coverFileName));
		}
		//数据库中的旧的信息
		UserInfo dbInfo = userInfoMapper.selectByUserId(userInfo.getUserId());
		//更新数据库
		userInfoMapper.updateByUserId(userInfo,userInfo.getUserId());
		//更新NickName  需要做其他操作
		String contactUpdateName  =null;
		if (!dbInfo.getNickName().equals(userInfo.getNickName())){
			contactUpdateName= userInfo.getNickName();
		}
		if (contactUpdateName==null){
			return;
		}
		//更新redis中的token的昵称信息
		TokenUserInfoDto tokenUserInfoDto = redisComponent.getTokenUserInfoDtoByUserid(userInfo.getUserId());
		tokenUserInfoDto.setNickName(contactUpdateName);
		redisComponent.setTokenUserInfoDto(tokenUserInfoDto);
		//修改其他表的冗余信息 并 发送ws通知
		chatSessionUserService.updateRedundanceInfo(contactUpdateName,userInfo.getUserId());
	}

    @Override
    public void updateUserStatus(Integer status, String userId) {
		UserStatusEnum statusEnum =  UserStatusEnum.getByCode(status);
		if (statusEnum==null){
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		UserInfo userInfo = new UserInfo();
		userInfo.setStatus(statusEnum.getStatus());
		userInfoMapper.updateByUserId(userInfo,userId);


	}

	@Override
	public void forceOffline(String userId) {
		//  强制下线
		MessageSendDto sendDto = new MessageSendDto();
		sendDto.setContactType(UserContactTypeEnum.USER.getType());
		sendDto.setMessageType(MessageTypeEnum.FORCE_OFF_LINE.getType());
		sendDto.setContactId(userId);
		messageHandler.sendMessage(sendDto);
	}

	public TokenUserInfoDto getTokenUserInfoDto(UserInfo userInfo){
		//登录成功，需要将用户信息保存起来
		TokenUserInfoDto tokenUserInfoDto = new TokenUserInfoDto();

		tokenUserInfoDto.setUserId(userInfo.getUserId());
		tokenUserInfoDto.setNickName(userInfo.getNickName());
		tokenUserInfoDto.setEmail(userInfo.getEmail());

		String adminEmails = appConfig.getAdminEmails();
		//判断当前登录用户是否是管理员
		if (adminEmails!=null  && ArraysUtil.contains(adminEmails.split(","),userInfo.getEmail() )){
			tokenUserInfoDto.setAdmin(true);
		}else {
			tokenUserInfoDto.setAdmin(false);
		}
		return tokenUserInfoDto;
	}


}